import sched
import threading
import time
from datetime import datetime
from tkinter import *
from tkinter import filedialog
from tkinter.ttk import *
from typing import Dict

import win32api
import win32gui
import win32print
from win32.lib import win32con

import log
import main_demo
from MyCalendar import MyCalendar

schedule = sched.scheduler(time.time, time.sleep)


def get_real_resolution():
    """获取真实的分辨率"""
    hDC = win32gui.GetDC(0)
    wide = win32print.GetDeviceCaps(hDC, win32con.DESKTOPHORZRES)
    high = win32print.GetDeviceCaps(hDC, win32con.DESKTOPVERTRES)
    return {"wide": wide, "high": high}


def get_screen_size():
    """获取缩放后的分辨率"""
    wide = win32api.GetSystemMetrics(win32con.SM_CXSCREEN)
    high = win32api.GetSystemMetrics(win32con.SM_CYSCREEN)
    return {"wide": wide, "high": high}


def get_scaling():
    """获取屏幕的缩放比例"""
    real_resolution = get_real_resolution()
    screen_size = get_screen_size()
    proportion = round(real_resolution['wide'] / screen_size['wide'], 2)
    return proportion


def label_log(parent):
    frame = LabelFrame(parent)
    frame.configure(text="日志")
    frame.place(x=25, y=580, width=950, height=200)
    mylist = Text(frame, width=945)  # 创建列表框
    mylist.pack(side=LEFT)
    return mylist


def button_start(parent):
    btn = Button(parent, text="立即执行", takefocus=False, )
    btn.place(x=675, y=40, width=100, height=30)
    return btn


def agreed_date(parent):
    x, y = (parent.winfo_screenwidth() - 1000) / 2, (parent.winfo_screenheight() - 800) / 2
    date_str = StringVar()
    date = Entry(parent, textvariable=date_str)
    date.place(x=125, y=40, width=200, height=30)
    date_str_gain = lambda: [
        date_str.set(date)
        for date in [MyCalendar((x, y), 'ur').selection()]
        if date]
    btn = Button(parent, text='预约日期:', command=date_str_gain)
    btn.place(x=25, y=40, width=100, height=30)
    return date


def button_timer(parent):
    btn = Button(parent, text="晚8点执行", takefocus=False, )
    btn.place(x=775, y=40, width=100, height=30)
    return btn


def upload_file(parent):
    select_file = filedialog.askopenfilename()
    f = open(select_file, encoding='utf-8')
    content = f.read()
    arr = content.split("\n")
    for item in arr:
        val = item.split(" ")
        parent.widget_dic["table"].insert('', END, values=val)
    f.close()
    log.info("导入数据")
    log.info(content)


def clean_up(parent):
    btn = Button(parent, text="清空", takefocus=False, command=lambda: clean(parent))
    btn.place(x=450, y=40, width=100, height=30)
    return btn


def clean(parent):
    x = parent.widget_dic["table"].get_children()
    for item in x:
        parent.widget_dic["table"].delete(item)
    log.info("清空数据")


def button_import(parent):
    btn = Button(parent, text="导入", takefocus=False, command=lambda: upload_file(parent))
    btn.place(x=550, y=40, width=100, height=30)
    return btn


def table(parent):
    # 表头字段 表头宽度
    columns = {"姓名": 200, "身份证号": 500, "手机号": 300}
    # 初始化表格 表格是基于Treeview，tkinter本身没有表格。show="headings" 为隐藏首列。
    tk_table = Treeview(parent, show="headings", columns=list(columns), )
    for text, width in columns.items():  # 批量设置列属性
        tk_table.heading(text, text=text, anchor='center')
        tk_table.column(text, anchor='center', width=width, stretch=False)  # stretch 不自动拉伸
    tk_table.place(x=25, y=100, width=950, height=300)
    return tk_table


def __scrollbar_hide(bar, widget):
    bar.lower(widget)


def __scrollbar_show(bar, widget):
    bar.lift(widget)


def scrollbar_autohide(bar, widget):
    __scrollbar_hide(bar, widget)
    widget.bind("<Enter>", lambda e: __scrollbar_show(bar, widget))
    bar.bind("<Enter>", lambda e: __scrollbar_show(bar, widget))
    widget.bind("<Leave>", lambda e: __scrollbar_hide(bar, widget))
    bar.bind("<Leave>", lambda e: __scrollbar_hide(bar, widget))


class WinGUI(Tk):
    widget_dic: Dict[str, Widget] = {}
    isLog = True

    def __init__(self):
        super().__init__()
        self.__win()
        self.widget_dic["agreed_date"] = agreed_date(self)
        self.widget_dic["clean_up"] = clean_up(self)
        self.widget_dic["button_import"] = button_import(self)
        self.widget_dic["button_start"] = button_start(self)
        self.widget_dic["button_timer"] = button_timer(self)

        self.widget_dic["table"] = table(self)
        self.widget_dic["label_log"] = label_log(self)

        self.protocol("WM_DELETE_WINDOW", self.on_closing)

    def on_closing(self):
        self.isLog = False
        sys.exit()

    def __win(self):
        self.title("故宫博物院自动化")
        # 设置窗口大小、居中
        width = 1000
        height = 800
        screenwidth = self.winfo_screenwidth()
        screenheight = self.winfo_screenheight()
        geometry = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
        self.geometry(geometry)
        self.resizable(width=False, height=False)

    # 自动隐藏滚动条

    def log(self):
        while self.isLog:
            while not log.queue_obj.empty():
                msg = log.queue_obj.get()
                msg = msg + '\n'
                self.widget_dic["label_log"].insert(END, msg)
                self.widget_dic["label_log"].see("end")
            time.sleep(0.2)


real_resolution = {}
screen_size = {}
scaling = {}
support = False
path = "res"


class Win(WinGUI):
    def __init__(self):
        threading.Thread(target=self.log).start()
        super().__init__()
        self.event_bind()
        global real_resolution
        global screen_size
        global scaling
        global support
        global path
        real_resolution = get_real_resolution()
        screen_size = get_screen_size()
        scaling = get_scaling()
        log.info("当前屏幕分辨率：" + str(real_resolution['wide']) + "*" + str(real_resolution['high']))
        log.info("当前屏幕缩放后分辨率：" + str(screen_size['wide']) + "*" + str(screen_size['high']))
        log.info("当前屏幕缩放比例：" + str(scaling))
        if real_resolution['wide'] == 2560 and real_resolution['high'] == 1440 and scaling == 1.0:
            support = True
            path = "res/2560_1440_1"
            log.info("受支持的分辨率")
        elif real_resolution['wide'] == 2560 and real_resolution['high'] == 1600 and scaling == 1.0:
            support = True
            path = "res"
            log.info("受支持的分辨率")
        else:
            support = False
            log.info("不受支持的分辨率")

    def event_bind(self):
        self.widget_dic["button_start"].bind('<Button>', self.start_execution)
        self.widget_dic["button_timer"].bind('<Button>', self.start_timer_execution)

    def start_task(self, number=None):
        try:
            if support:
                log.info("开始任务")
                agreed_date = self.widget_dic["agreed_date"].get()
                user_list = []
                x = self.widget_dic["table"].get_children()
                for item in x:
                    value = self.widget_dic["table"].item(item)['values']
                    user_list.append(value)
                if len(user_list) > 0:
                    if number is not None:
                        second = get_seconds(number)
                        schedule.enter(second, 0, main_demo.start_task, (user_list, agreed_date, path))
                        schedule.run()
                    else:
                        main_demo.start_task(user_list, agreed_date, path)
                else:
                    log.info("请导入数据")
                log.info("任务结束")
            else:
                log.info("不支持，你别点了!!!")
        except BaseException as error:
            log.info("线程异常结束了"+type(error).__name__)


    def start_execution(self, evt):
        threading.Thread(target=self.start_task).start()

    def start_timer_execution(self, evt):
        threading.Thread(target=self.start_task, args=(20,)).start()

def get_seconds(sched_date):
    start_date = datetime.now()
    end_time = datetime(datetime.now().year, datetime.now().month, datetime.now().day, int(sched_date), 0, 0)
    diff = end_time - start_date
    log.info(str(diff.total_seconds()) + "秒后开始任务")
    return diff.total_seconds()


if __name__ == "__main__":
    sys.setrecursionlimit(10000000)
    win = Win()
    win.mainloop()
